
#pragma once

#if defined(__GNUC__) || defined(__MINGW32__) || defined(__MINGW__)
    #pragma GCC diagnostic push
    #pragma GCC diagnostic ignored "-Weffc++"
#endif


namespace tools
{
    namespace variant_detail
    {
//-----------------------------------------------------------------------------------------
        template<class T>struct Out
        {
            template<class Stream> static void ToString(const void* const value, Stream& ss)
            {
                const T& v = *static_cast<const T*const >(value);
                ss << v;
            }
        private:
            enum { eTYPE = Type2Enum<T>::eTYPE };
        };
//-----------------------------------------------------------------------------------------
        template<>struct Out<SEmpty>
        {
            template<class Stream> static void ToString(const void* const, Stream& ss){ ss << "empty"; }
            static const char* ToString(){ return "empty"; }
        };
//-----------------------------------------------------------------------------------------
        template<>struct Out<bool>
        {
            template<class Stream> static void ToString(const void* const value, Stream& ss)
            {
                const bool& v = *static_cast<const bool*const >(value);
                ss << (v? "true": "false");
            }
        };
//-----------------------------------------------------------------------------------------
        template<>struct Out<V::Byte>
        {
            template<class Stream> static void ToString(const void* const value, Stream& ss)
            {
                const V::Byte& v = *static_cast<const V::Byte*const >(value);
                ss << "'"<<v<<"'";
            }
        };
//-----------------------------------------------------------------------------------------
        template<>struct Out<V::WChar>
        {
            template<class Stream> static void ToString(const void* const value, Stream& ss)
            {
                const V::Byte& v = *static_cast<const V::Byte*const >(value);
                ss << "'"<<v<<"'";
            }
        };
//-----------------------------------------------------------------------------------------
        template<>struct Out<V::I8>
        {
            template<class Stream> static void ToString(const void* const value, Stream& ss)
            {
                const V::I8& v = *static_cast<const V::I8*const >(value);
                ss << static_cast<int>(v);
            }
        };
//-----------------------------------------------------------------------------------------
        template<>struct Out<V::U8>
        {
            template<class Stream> static void ToString(const void* const value, Stream& ss)
            {
                const V::U8& v = *static_cast<const V::U8*const >(value);
                ss << static_cast<unsigned int>(v);
            }
        };
//-----------------------------------------------------------------------------------------
        template<>struct Out<V::Blob>
        {
            template<class Stream> static void ToString(const void* const value, Stream& ss)
            {
                const V::Blob& v = *static_cast<const V::Blob*const >(value);
                ss << "blob("<< v.size()<<")";
            }
        };
//-----------------------------------------------------------------------------------------
        template<>struct Out<V::Str>
        {
            template<class Stream> static void ToString(const void* const value, Stream& ss)
            {
                const V::Str& v = *static_cast<const V::Str*const >(value);
                ss << "\""<< v.c_str() <<"\"";
            }
        };
//-----------------------------------------------------------------------------------------
        template<>struct Out<V::WStr>
        {
            template<class Stream> static void ToString(const void* const value, Stream& ss)
            {
                const V::WStr& v = *static_cast<const V::WStr*const >(value);
                ss << "\""<< v.c_str() <<"\"";
            }
        };
//-----------------------------------------------------------------------------------------
        template<>struct Out<V::Record>
        {
            template<class Stream> static void ToString(const void* const value, Stream& ss)
            {
                const V::Record& v = *static_cast<const V::Record*const >(value);
                ss << "Record(\""<< v.first <<"\" : "<< v.second.ToString()<<")";
            }
        };
//-----------------------------------------------------------------------------------------
        template<>struct Out<V::Map>
        {
            template<class Stream> static void ToString(const void* const, Stream& ss){ ss << "map"; }
        };
        template<>struct Out<V::Vec>
        {
            template<class Stream> static void ToString(const void* const, Stream& ss){ ss << "vec"; }
        };
        template<>struct Out<V::List>
        {
            template<class Stream> static void ToString(const void* const, Stream& ss){ ss << "list"; }
        };
        template<>struct Out<V::Records>
        {
            template<class Stream> static void ToString(const void* const, Stream& ss){ ss << "records"; }
        };
//-----------------------------------------------------------------------------------------

    }//namespace value_detail
}//namespace tools


#if defined(__GNUC__) || defined(__MINGW32__) || defined(__MINGW__)
    #pragma GCC diagnostic pop
#endif
